package com.test.lucene;

import java.io.IOException;
import java.util.Collection;

import com.test.lucene.helper.Book;
import com.test.lucene.helper.Books;
import com.test.lucene.helper.SearchParameters;
import com.test.lucene.helper.SharedParameters;
import com.test.lucene.index.DocumentCollection;

/**
 * Search a Lucene repository.
 * 
 * @author Patrick Kimber
 * 
 */
public final class Search extends Manager {

    /**
     * Search for documents in the Lucene repository.
     * 
     * @param args
     *            Command line parameters.
     * @throws LuceneException
     *             If a Lucene operation fails.
     * @throws IOException
     *             If an IO operation fails.
     * @throws InterruptedException
     *             If the sleep is interrupted.
     */
    public static void main(final String[] args) throws LuceneException,
            IOException, InterruptedException {
        Search search = new Search(args);
        if (search.isValid()) {
            search.run();
        }
    }

    /** The application parameters. */
    private SearchParameters parameters;

    /**
     * Constructor.
     * 
     * @param args
     *            Command line parameters.
     */
    public Search(final String[] args) {
        super(args);
    }

    /**
     * Write documents to a Lucene repository.
     * 
     * @throws LuceneException
     *             If a Lucene operation fails.
     * @throws IOException
     *             If an IO operation fails.
     * @throws InterruptedException
     *             If the sleep is interrupted.
     */
    public void run() throws LuceneException, IOException, InterruptedException {
        DocumentCollection collection = null;
        try {
            collection = createCollection();
            search(collection);
        } finally {
            if (collection != null) {
                collection.close();
            }
        }
        System.out.println("Complete");
    }

    /**
     * Search the document collection.
     * 
     * @param collection
     *            The Lucene collection.
     * @throws LuceneException
     *             If a Lucene operation fails.
     * @throws InterruptedException
     *             If the thread sleep statement is interrupted.
     */
    private void search(final DocumentCollection collection)
            throws LuceneException, InterruptedException {
        setFinishTime();
        long defaultSleep = getDefaultSleep();
        displayStatus(defaultSleep);
        do {
            for (int i = 0; i < Books.getCount(); ++i) {
                Book book = Books.getBook(i);
                String criteria = book.getTitle();
                System.out.println("  Found "
                        + search(collection, criteria).size() + " for ["
                        + criteria + "]");
                Thread.sleep(defaultSleep);
            }
        } while (!isFinished());
        System.out.println();
    }

    /**
     * Search the document collection.
     * 
     * @param collection
     *            The Lucene document collection.
     * @param criteria
     *            The search criteria.
     * @return The search results.
     * @throws LuceneException
     *             If a Lucene operation fails.
     */
    private Collection search(final DocumentCollection collection,
            final String criteria) throws LuceneException {
        return collection.search(criteria);
    }

    /**
     * Display status.
     * 
     * @param defaultSleep
     *            The number of milliseconds to sleep between each request.
     */
    private void displayStatus(final long defaultSleep) {
        System.out.println("Searching for books...");
        System.out.println("  in:       "
                + getSharedParameters().getRepositoryFolder());
        System.out.println("  until:    " + getFinishTime().toString());
        System.out.println("  sleeping: " + defaultSleep
                + " milliseconds between search requests.\n");
    }

    /**
     * Create the parameters for this class.
     * 
     * @param args
     *            command line parameters.
     */
    protected void createParameters(final String[] args) {
        parameters = new SearchParameters(this.getClass().getName(), args);
    }

    /** @return the parameters. */
    protected SharedParameters getSharedParameters() {
        return parameters;
    }
}
